#include "job_manager.hpp"
#include "clock.hpp"
#include "logger.hpp"
#include "kernel.hpp"
#include "FSCP_Utils.hpp"
#include <iomanip>

using namespace qOS;

//==============================================================================
// JobManager implementation
JobManager::JobManager(size_t maxJobs)
    : maxConcurrentJobs(maxJobs)
    , currentJobCount(0)
{}
//==============================================================================
JobManager::~JobManager()
{
    cleanup();
}
//==============================================================================
bool JobManager::initialize(core &os)
{
    // Create monitoring Task
    task monitorTask(0);
    
    // Static callback function that can be converted to taskFcn_t
    static taskFcn_t monitorCallbackWrapper = [](event_t e, uint64_t securityToken) {
        // This lambda must be captureless to convert to function pointer
        (void)e;
        (void)securityToken;
        // Basic monitoring logic placeholder
    };

    bool success = os.add(monitorTask, monitorCallbackWrapper, core::LOWEST_PRIORITY,
                          1000_ms, task::PERIODIC, taskState::ENABLED_STATE, this);

    if (success) {
        monitorTask.setName("JobMonitor");
        logger::out(logger::info) << "Job Manager initialized";
    }
    else {
        logger::out(logger::error) << "Failed to initialize Job Manager";
    }

    return success;
}
//==============================================================================
bool JobManager::addJob(Job &job)
{
    if (currentJobCount >= maxConcurrentJobs) {
        logger::out(logger::warning) << "Maximum concurrent job limit reached";
        return false;
    }

    bool success = jobList.insert(&job);
    if (success) {
        currentJobCount++;
        logger::out(logger::info) << "Job added to manager";
    }
    else {
        logger::out(logger::error) << "Failed to add job to manager";
    }

    return success;
}
//==============================================================================
bool JobManager::removeJob(Job &job)
{
    bool success = jobList.remove(&job);
    if (success) {
        currentJobCount--;
        logger::out(logger::info) << "Job removed from manager";
    }
    else {
        logger::out(logger::warning) << "Job not found in manager";
    }

    return success;
}
//==============================================================================
bool JobManager::addJobAndSubmit(Job &job, core &os, task tasks[], size_t count)
{
    if (currentJobCount >= maxConcurrentJobs) {
        logger::out(logger::warning) << "Maximum concurrent job limit reached";
        return false;
    }

    bool success = jobList.insert(&job);
    if (success) {
        currentJobCount++;
        logger::out(logger::info) << "Job added to manager";
        
        // Submit the job with tasks
        if (!job.submit(os, tasks, count, job.GetSecurityToken())) {
            logger::out(logger::error) << "Failed to submit job after adding to manager";
            jobList.remove(&job);
            currentJobCount--;
            return false;
        }
        
        logger::out(logger::info) << "Job added and submitted successfully";
    }
    else {
        logger::out(logger::error) << "Failed to add job to manager";
    }

    return success;
}
//==============================================================================
bool JobManager::startAllJobs(core &os)
{
    bool allSuccess = true;
    
    for (listIterator it = jobList.begin();  it.untilEnd();  it++) {
        Job *job = it.get<Job*>();
        if (job != nullptr) {
            if (!job->submit(os, nullptr, 0, job->GetSecurityToken())) {
                allSuccess = false;
                logger::out(logger::error) << "Failed to submit job";
            }
        }
    }

    if (allSuccess) {
        logger::out(logger::info) << "All jobs started successfully";
    }

    return allSuccess;
}
//==============================================================================
void JobManager::pauseAllJobs()
{
    for (listIterator it = jobList.begin();  it.untilEnd();  it++) {
        Job *job = it.get<Job*>();
        if (job != nullptr) {
            job->pause(job->GetSecurityToken());
        }
    }
    
    logger::out(logger::info) << "All jobs paused";
}
//==============================================================================
void JobManager::resumeAllJobs()
{
    for (listIterator it = jobList.begin();  it.untilEnd();  it++) {
        Job *job = it.get<Job*>();
        if (job != nullptr) {
            job->resume(job->GetSecurityToken());
        }
    }
    
    logger::out(logger::info) << "All jobs resumed";
}
//==============================================================================
bool JobManager::pauseJob(const char *name)
{
    if (name == nullptr) {
        return false;
    }

    for (listIterator it = const_cast<list&>(jobList).begin(); it.untilEnd(); it++) {
        Job *job = it.get<Job*>();
        if (job != nullptr) {
            // For now, pause the first job found
            // In a real implementation, we'd need to add getName() method to Job
            job->pause(job->GetSecurityToken());
            return true;
        }
    }

    logger::out(logger::warning) << "Job not found for pause: " << name;
    return false;
}
//==============================================================================
bool JobManager::resumeJob(const char *name)
{
    if (name == nullptr) {
        return false;
    }

    for (listIterator it = const_cast<list&>(jobList).begin(); it.untilEnd(); it++) {
        Job *job = it.get<Job*>();
        if (job != nullptr) {
            // For now, resume first job found
            // In a real implementation, we'd need to add getName() method to Job
            job->resume(job->GetSecurityToken());
            return true;
        }
    }

    logger::out(logger::warning) << "Job not found for resume: " << name;
    return false;
}
//==============================================================================
size_t JobManager::forcePauseAllJobs()
{
    size_t pausedCount = 0;

    for (listIterator it = const_cast<list&>(jobList).begin(); it.untilEnd(); it++) {
        Job *job = it.get<Job*>();
        if (job != nullptr) {
            if (job->forcePause(job->GetSecurityToken())) {
                pausedCount++;
            }
        }
    }

    logger::out(logger::info) << "Force paused " << pausedCount << " jobs";
    return pausedCount;
}
//==============================================================================
size_t JobManager::getPausedJobCount() const
{
    size_t count = 0;

    // Use const_cast to get a non-const reference for iteration
    list &nonConstList = const_cast<list&>(jobList);
    for (listIterator it = nonConstList.begin(); it.untilEnd(); it++) {
        Job *job = it.get<Job*>();
        if (job != nullptr && job->isPaused()) {
            count++;
        }
    }

    return count;
}
//==============================================================================
size_t JobManager::getJobCount() const
{
    return currentJobCount;
}
//==============================================================================
size_t JobManager::getRunningJobCount() const
{
    size_t count = 0;
    
    // Use const_cast to get a non-const reference for iteration
    list &nonConstList = const_cast<list&>(jobList);
    for (listIterator it = nonConstList.begin();  it.untilEnd();  it++) {
        Job *job = it.get<Job*>();
        if (job != nullptr && job->getState() == JobState::RUNNING) {
            count++;
        }
    }
    
    return count;
}
//==============================================================================
Job* JobManager::findJobByName(const char *name)
{
    if (name == nullptr) {
        return nullptr;
    }

    for (listIterator it = jobList.begin();  it.untilEnd();  it++) {
        Job *job = it.get<Job*>();
        // Job class needs to provide getName() method
        // Temporarily return the first Job
        if (job != nullptr) {
            return job;
        }
    }

    return nullptr;
}
//==============================================================================
void JobManager::cleanup()
{
    jobList.clean();
    currentJobCount = 0;
}
//==============================================================================
void JobManager::printStatus()
{
    logger::out(logger::info) << "Job Manager Status:";
    logger::out(logger::info) << "- Total Jobs: " << currentJobCount;
    logger::out(logger::info) << "- Running Jobs: " << getRunningJobCount();
    logger::out(logger::info) << "- Paused Jobs: " << getPausedJobCount();
    logger::out(logger::info) << "- Max Concurrent Jobs: " << maxConcurrentJobs;
    
    // Print status of each Job
    for (listIterator it = jobList.begin();  it.untilEnd();  it++) {
        Job *job = it.get<Job*>();
        if (job != nullptr) {
            JobStatistics stats = job->getStatistics();
            const char* stateStr = "UNKNOWN";
            switch (job->getState()) {
                case JobState::CREATED: stateStr = "CREATED"; break;
                case JobState::INITIALIZED: stateStr = "INITIALIZED"; break;
                case JobState::RUNNING: stateStr = "RUNNING"; break;
                case JobState::PAUSED: stateStr = "PAUSED"; break;
                case JobState::COMPLETED: stateStr = "COMPLETED"; break;
                case JobState::ERROR: stateStr = "ERROR"; break;
            }

            logger::out(logger::info) << "  Job - State: " << stateStr
                                     << " - Executions: " << stats.executionCount
                                     << " - Success: " << stats.successCount
                                     << " - Failures: " << stats.failureCount;

            if (job->isPaused()) {
                logger::out(logger::info) << "    Pause Duration: " << job->getPauseDuration() << " microseconds";
            }
        }
    }
}
//==============================================================================
// Private method implementations
void JobManager::monitorCallback(event_t e, uint64_t securityToken, JobManager *manager)
{
    if (e.firstCall()) {
        logger::out(logger::info) << "Job Manager monitor started";
    }

    // Security token verification
    if (securityToken != e.thisTask().GetSecurityToken()) {
        return;
    }

    // Monitor status of all Jobs
    manager->monitorJobs();
}
//==============================================================================
void JobManager::monitorJobs()
{
    for (listIterator it = jobList.begin();  it.untilEnd();  it++) {
        Job *job = it.get<Job*>();
        if (job != nullptr) {
            JobState state = job->getState();
            
            // Handle completed Jobs
            if ((state == JobState::COMPLETED) || (state == JobState::ERROR)) {
                handleCompletedJob(job, job->GetSecurityToken());
            }
        }
    }
}
//==============================================================================
void JobManager::handleCompletedJob(Job *job, uint64_t securityToken)
{
    // Enhanced Token Execution Check for functional safety in JobManager
    if (job != nullptr && securityToken != job->GetSecurityToken()) {
        logger::out(logger::error) << "SECURITY BREACH: JobManager token mismatch for job: "
                                 << " (expected: " << job->GetSecurityToken()
                                 << ", received: " << securityToken << ")";
        
        if (nullptr != os.mRunningErrorHandler) {
            char buf[256];
            snprintf(buf, sizeof(buf), "Functional safety: JobManager security breach");
            os.mRunningErrorHandler(FSCP_ErrorType::SECURITY_BREACH, buf, nullptr);
        }
        return;
    }

    // Mark variable as used to avoid compiler warning
    JobStatistics stats = job->getStatistics();
    (void)stats;
    
    if (job->getState() == JobState::COMPLETED) {
        logger::out(logger::info) << "Job completed: " << job->getStatistics();
    }
    else {
        logger::out(logger::error) << "Job failed: " << job->getStatistics();
    }
    
    // Here you can add post-Job completion processing logic
    // For example: log recording, trigger callbacks, start next Job, etc.
}

//==============================================================================
void JobManager::performSecurityAudit() const
{
    // Comprehensive security audit for all jobs
    logger::out(logger::info) << "SECURITY: Performing comprehensive security audit";
    
    size_t totalJobs = 0;
    size_t runningJobs = 0;
    size_t pausedJobs = 0;
    size_t failedJobs = 0;
    
    for (listIterator it = const_cast<list&>(jobList).begin(); it.untilEnd(); it++) {
        Job* job = it.get<Job*>();
        if (job != nullptr) {
            totalJobs++;
            
            JobState state = job->getState();
            switch (state) {
                case JobState::RUNNING:
                    runningJobs++;
                    break;
                case JobState::PAUSED:
                    pausedJobs++;
                    break;
                case JobState::ERROR:
                    failedJobs++;
                    break;
                default:
                    break;
            }
            
            // Individual job security analysis
            JobStatistics stats = job->getStatistics();
            if (stats.executionCount > 0) {
                double failureRate = static_cast<double>(stats.failureCount) / stats.executionCount;
                if (failureRate > 0.5) {
                    logger::out(logger::warning) << "SECURITY: High failure rate (" 
                                                << (failureRate * 100) << "%) for job: " 
                                                << job->getName();
                }
            }
        }
    }
    
    // System-level security summary
    logger::out(logger::info) << "SECURITY: Audit summary - Total: " << totalJobs
                               << ", Running: " << runningJobs
                               << ", Paused: " << pausedJobs 
                               << ", Failed: " << failedJobs;
}
